home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / RTrace-1.0-src / shadmod2.c < prev    next >
Text File  |  1992-08-24  |  21KB  |  562 lines

  1. /*
  2.  * Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
  3.  * All rights reserved.
  4.  *
  5.  * This code received contributions from the following people:
  6.  *
  7.  *  Roman Kuchkuda      - basic ray tracer
  8.  *  Mark VandeWettering - MTV ray tracer
  9.  *  Augusto Sousa       - overall, shading model
  10.  *  Paul Strauss        - shading model
  11.  *  Craig Kolb          - textures
  12.  *  David Buck          - textures
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted
  15.  * provided that the above copyright notice and this paragraph are
  16.  * duplicated in all such forms and that any documentation,
  17.  * advertising materials, and other materials related to such
  18.  * distribution and use acknowledge that the software was developed
  19.  * by Antonio Costa, at INESC-Norte. The name of the author and
  20.  * INESC-Norte may not be used to endorse or promote products derived
  21.  * from this software without specific prior written permission.
  22.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  23.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  24.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  25.  */
  26. #include "defs.h"
  27. #include "extern.h"
  28.  
  29. /**********************************************************************
  30.  *    RAY TRACING - Shade Model 2 - Version 7.0                       *
  31.  *                                                                    *
  32.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  33.  *    ADAPTED BY : Antonio Costa, INESC-Norte, June 1989              *
  34.  *    MODIFIED BY: Antonio Costa, INESC-Norte, March 1992             *
  35.  **********************************************************************/
  36.  
  37. /***** Shading Paul Strauss model *****/
  38. #define LEFT  (1 SHL shade_level)
  39. #define RIGHT (1 SHL (shade_level + 1))
  40.  
  41. static real
  42. geometric(k)
  43.   REG real        k;
  44. {
  45. #define KG (1.01)
  46.  
  47.   REG real        t;
  48.  
  49.   t = 1.0 / SQR(1.0 - KG);
  50.   t = (t - 1.0 / SQR(k - KG)) / (t - 1.0 / SQR(KG));
  51.   if (t < ROUNDOFF)
  52.     return 0.0;
  53.   return t;
  54.  
  55. #undef KG
  56. }
  57. static real
  58. fresnel(k)
  59.   REG real        k;
  60. {
  61. #define KF (1.12)
  62.  
  63.   REG real        t;
  64.  
  65.   t = 1.0 / SQR(KF);
  66.   t = (1.0 / SQR(k - KF) - t) / (1.0 / SQR(1.0 - KF) - t);
  67.   if (t < ROUNDOFF)
  68.     return 0.0;
  69.   return t;
  70.  
  71. #undef KF
  72. }
  73. static real
  74. calculate_factor(cosine, geometric_incidence, fresnel_specular)
  75.   real            cosine, geometric_incidence;
  76.   real           *fresnel_specular;
  77. {
  78.   REG real        t;
  79.  
  80.   if (cosine < ROUNDOFF)
  81.   {
  82.     *fresnel_specular = 1.0;
  83.     return 0.0;
  84.   }
  85.   if (cosine > 1.0 - ROUNDOFF)
  86.   {
  87.     *fresnel_specular = 0.0;
  88.     return 0.0;
  89.   }
  90.   t = ARCCOS(MIN(1.0, cosine)) / PI * 2.0;
  91.   *fresnel_specular = fresnel(t);
  92.   if (geometric_incidence < ROUNDOFF)
  93.     return 0.0;
  94.   else
  95.     return (*fresnel_specular * geometric_incidence * geometric(t));
  96. }
  97.  
  98. #ifdef THINK_C
  99.  
  100. /* On the mac, SCREEN_SIZE_X_MAX is not a constant, so previous_repetitions
  101.     is set manually from the mac segment */
  102.         
  103. extern short int previous_repetitions;
  104.  
  105. #else
  106.  
  107. static short int  previous_repetitions = SCREEN_SIZE_X_MAX;
  108.  
  109. #endif
  110.  
  111. static xyz_struct previous_normal, previous_reflected;
  112. static rgb_struct previous_diffuse, previous_specular;
  113.  
  114. void
  115. shade_strauss(position, normal, ray, object, color)
  116.   xyz_ptr         position, normal;     /* Normal may be modified */
  117.   ray_ptr         ray;
  118.   object_ptr      object;
  119.   rgb_ptr         color;
  120. {
  121. #define SPECULAR_PEAK (0.1)
  122.  
  123.   REG int         l;
  124.   REG real        k, diffuse, specular, intensity;
  125.   real            geometric_incidence, fresnel_specular;
  126.   boolean         refractive, opposite_light;
  127.   rgb_struct      brightness, level;
  128.   rgb_struct      surface_diffuse, surface_specular, surface_transparent;
  129.   rgb_struct      new_color, distributed_color, new_specular;
  130.   xyz_struct      old_normal, old_reflected, lighting;
  131.   ray_struct      reflected, refracted, distributed;
  132.   surface_struct  new_surface;
  133.   int             id, ambient_diffuse_rays, ambient_specular_rays;
  134.  
  135.   STRUCT_ASSIGN(new_surface, *(surface[object->surface_id]));
  136.   k = -2.0 * DOT_PRODUCT(ray->vector, *normal);
  137.   reflected.vector.x = k * normal->x + ray->vector.x;
  138.   reflected.vector.y = k * normal->y + ray->vector.y;
  139.   reflected.vector.z = k * normal->z + ray->vector.z;
  140.   if (normal_mode == 0)
  141.   {
  142.     if (k < 0.0)
  143.     {
  144.       normal->x = -(normal->x);
  145.       normal->y = -(normal->y);
  146.       normal->z = -(normal->z);
  147.     }
  148.   } else
  149.   if ((k < 0.0) AND ray->inside)
  150.   {
  151.     normal->x = -(normal->x);
  152.     normal->y = -(normal->y);
  153.     normal->z = -(normal->z);
  154.   }
  155.   STRUCT_ASSIGN(old_normal, *normal);
  156.   if ((texture_mode != 0) AND(object->texture != NULL))
  157.   {
  158.     if (normal_check_mode AND object->texture_modify_normal)
  159.       STRUCT_ASSIGN(old_reflected, reflected.vector);
  160.     surface_texture(position, normal, &new_surface, object->texture);
  161.     if (normal_check_mode AND object->texture_modify_normal)
  162.     {
  163.       k = -2.0 * DOT_PRODUCT(ray->vector, *normal);
  164.       reflected.vector.x = k * normal->x + ray->vector.x;
  165.       reflected.vector.y = k * normal->y + ray->vector.y;
  166.       reflected.vector.z = k * normal->z + ray->vector.z;
  167.       if (DOT_PRODUCT(reflected.vector, old_normal) < ROUNDOFF)
  168.       {
  169.         STRUCT_ASSIGN(*normal, old_normal);
  170.         STRUCT_ASSIGN(reflected.vector, old_reflected);
  171.       }
  172.     }
  173.   }
  174.   STRUCT_ASSIGN(surface_diffuse, new_surface.diffuse);
  175.   STRUCT_ASSIGN(surface_specular, new_surface.specular);
  176.   STRUCT_ASSIGN(surface_transparent, new_surface.transparent);
  177.   new_surface.diffuse.r *= new_surface.color.r;
  178.   new_surface.diffuse.g *= new_surface.color.g;
  179.   new_surface.diffuse.b *= new_surface.color.b;
  180.   k *= 0.5;
  181.   if (k > 1.0 - ROUNDOFF)
  182.     geometric_incidence = 1.0;
  183.   else
  184.     if (k < ROUNDOFF)
  185.       geometric_incidence = 0.0;
  186.     else
  187.       geometric_incidence = geometric(ARCCOS(k) / PI * 2.0);
  188.   color->r = 0.0;
  189.   color->g = 0.0;
  190.   color->b = 0.0;
  191.   /* Refractions */
  192.   refractive = FALSE;
  193.   if (COLOR_BIG(surface_transparent, ROUNDOFF)
  194.       AND(shade_level < last_shade_level))
  195.   {
  196.     level.r = ray->level.r * surface_transparent.r;
  197.     level.g = ray->level.g * surface_transparent.g;
  198.     level.b = ray->level.b * surface_transparent.b;
  199.     if (COLOR_BIG(level, threshold_level))
  200.     {
  201.       STRUCT_ASSIGN(refracted.vector, ray->vector);
  202.       if (refract(&refracted, normal, ray->inside, object->refraction))
  203.       {
  204.         refractive = TRUE;
  205.         if (shade_level < RAY_CACHE_LEVEL_MAX)
  206.           ray_node += RIGHT;
  207.         POSINC(shade_level);
  208.         if (shade_level > shade_level_max)
  209.           shade_level_max = shade_level;
  210.         STRUCT_ASSIGN(refracted.level, level);
  211.         refracted.inside = NOT ray->inside;
  212.         REALINC(refracted_rays);
  213.         if (SELF_INTERSECT(object->object_type, refracted.inside))
  214.           id = NO_OBJECTS;
  215.         else
  216.           id = object->id;
  217.         k = calculate_factor(-DOT_PRODUCT(*normal, refracted.vector),
  218.                              geometric_incidence, &fresnel_specular);
  219.         new_specular.r = MIN(1.0, surface_specular.r + (surface_specular.r +
  220.           SPECULAR_PEAK) * k);
  221.         new_specular.g = MIN(1.0, surface_specular.g + (surface_specular.g +
  222.           SPECULAR_PEAK) * k);
  223.         new_specular.b = MIN(1.0, surface_specular.b + (surface_specular.b +
  224.           SPECULAR_PEAK) * k);
  225.         specular = DOT_PRODUCT(ray->vector, refracted.vector);
  226.         if (specular > ROUNDOFF)
  227.           specular = POWER(specular, new_surface.phong_factor);
  228.         else
  229.           specular = 0.0;
  230.         new_surface.transparent.r *= (1.0 - specular * new_specular.r) /
  231.           (1.0 + ROUNDOFF - surface_specular.r);
  232.         new_surface.transparent.g *= (1.0 - specular * new_specular.g) /
  233.           (1.0 + ROUNDOFF - surface_specular.g);
  234.         new_surface.transparent.b *= (1.0 - specular * new_specular.b) /
  235.           (1.0 + ROUNDOFF - surface_specular.b);
  236.         new_surface.transparent.r = MIN(1.0, new_surface.transparent.r);
  237.         new_surface.transparent.g = MIN(1.0, new_surface.transparent.g);
  238.         new_surface.transparent.b = MIN(1.0, new_surface.transparent.b);
  239.         new_surface.transparent.r *= 1.0 + new_surface.metal_factor.r * (1.0 -
  240.           fresnel_specular) * (new_surface.color.r - 1.0);
  241.         new_surface.transparent.g *= 1.0 + new_surface.metal_factor.g * (1.0 -
  242.           fresnel_specular) * (new_surface.color.g - 1.0);
  243.         new_surface.transparent.b *= 1.0 + new_surface.metal_factor.b * (1.0 -
  244.           fresnel_specular) * (new_surface.color.b - 1.0);
  245.         if (intersect_all(id, position, &refracted, &new_color) > 0.0)
  246.         {
  247.           color->r += new_color.r * new_surface.transparent.r;
  248.           color->g += new_color.g * new_surface.transparent.g;
  249.           color->b += new_color.b * new_surface.transparent.b;
  250.         } else
  251.         {
  252.           color->r += back_color.r * new_surface.transparent.r;
  253.           color->g += back_color.g * new_surface.transparent.g;
  254.           color->b += back_color.b * new_surface.transparent.b;
  255.         }
  256.         POSDEC(shade_level);
  257.         if (shade_level < RAY_CACHE_LEVEL_MAX)
  258.           ray_node -= RIGHT;
  259.       } else
  260.       {
  261.         /* TIR */
  262.         new_surface.specular.r += surface_transparent.r;
  263.         new_surface.specular.g += surface_transparent.g;
  264.         new_surface.specular.b += surface_transparent.b;
  265.         STRUCT_ASSIGN(surface_specular, new_surface.specular);
  266.       }
  267.     }
  268.   }
  269.   /* Reflections */
  270.   if (COLOR_BIG(surface_specular, ROUNDOFF)
  271.       AND(shade_level < last_shade_level))
  272.   {
  273.     level.r = ray->level.r * surface_specular.r;
  274.     level.g = ray->level.g * surface_specular.g;
  275.     level.b = ray->level.b * surface_specular.b;
  276.     if (COLOR_BIG(level, threshold_level))
  277.     {
  278.       if (shade_level < RAY_CACHE_LEVEL_MAX)
  279.         ray_node += LEFT;
  280.       POSINC(shade_level);
  281.       if (shade_level > shade_level_max)
  282.         shade_level_max = shade_level;
  283.       STRUCT_ASSIGN(reflected.level, level);
  284.       reflected.inside = ray->inside;
  285.       REALINC(reflected_rays);
  286.       if (SELF_INTERSECT(object->object_type, reflected.inside))
  287.         id = NO_OBJECTS;
  288.       else
  289.         id = object->id;
  290.       k = calculate_factor(DOT_PRODUCT(*normal, reflected.vector),
  291.                            geometric_incidence, &fresnel_specular);
  292.       new_surface.specular.r = MIN(1.0, surface_specular.r +
  293.         (surface_specular.r + SPECULAR_PEAK) * k);
  294.       new_surface.specular.g = MIN(1.0, surface_specular.g +
  295.         (surface_specular.g + SPECULAR_PEAK) * k);
  296.       new_surface.specular.b = MIN(1.0, surface_specular.b +
  297.         (surface_specular.b + SPECULAR_PEAK) * k);
  298.       new_surface.specular.r *= 1.0 + new_surface.metal_factor.r * (1.0 -
  299.         fresnel_specular) * (new_surface.color.r - 1.0);
  300.       new_surface.specular.g *= 1.0 + new_surface.metal_factor.g * (1.0 -
  301.         fresnel_specular) * (new_surface.color.g - 1.0);
  302.       new_surface.specular.b *= 1.0 + new_surface.metal_factor.b * (1.0 -
  303.         fresnel_specular) * (new_surface.color.b - 1.0);
  304.       if (intersect_all(id, position, &reflected, &new_color) > 0.0)
  305.       {
  306.         color->r += new_color.r * new_surface.specular.r;
  307.         color->g += new_color.g * new_surface.specular.g;
  308.         color->b += new_color.b * new_surface.specular.b;
  309.       } else
  310.       {
  311.         color->r += back_color.r * new_surface.specular.r;
  312.         color->g += back_color.g * new_surface.specular.g;
  313.         color->b += back_color.b * new_surface.specular.b;
  314.       }
  315.       POSDEC(shade_level);
  316.       if (shade_level < RAY_CACHE_LEVEL_MAX)
  317.         ray_node -= LEFT;
  318.     }
  319.   }
  320.   /* Ambient */
  321.   if ((shade_level >= last_ambient_level) OR(ambient_sample_rays == 0))
  322.   {
  323.     color->r += light_ambient.r * new_surface.diffuse.r;
  324.     color->g += light_ambient.g * new_surface.diffuse.g;
  325.     color->b += light_ambient.b * new_surface.diffuse.b;
  326.   } else
  327.   {
  328.     STRUCT_ASSIGN(new_surface.specular, surface_specular);
  329.     new_surface.specular.r *= new_surface.color.r * (1.0 -
  330.       new_surface.metal_factor.r) + new_surface.metal_factor.r;
  331.     new_surface.specular.g *= new_surface.color.g * (1.0 -
  332.       new_surface.metal_factor.g) + new_surface.metal_factor.g;
  333.     new_surface.specular.b *= new_surface.color.b * (1.0 -
  334.       new_surface.metal_factor.b) + new_surface.metal_factor.b;
  335.     diffuse = (surface_diffuse.r + surface_diffuse.g +
  336.       surface_diffuse.b) / 3.0;
  337.     specular = (surface_specular.r + surface_specular.g +
  338.       surface_specular.b) / 3.0;
  339.     if (diffuse + specular > ROUNDOFF)
  340.     {
  341.       if (ABS(diffuse + specular - 1.0) > ROUNDOFF)
  342.       {
  343.         k = diffuse + specular;
  344.         diffuse /= k;
  345.         specular /= k;
  346.       }
  347.       if ((shade_level == 0) AND(distributed_cache_mode != 0)
  348.           AND(previous_repetitions <= distributed_cache_repetitions)
  349.           AND(DOT_PRODUCT(old_normal, previous_normal) > threshold_vector)
  350.           AND(DOT_PRODUCT(reflected.vector, previous_reflected) >
  351.               threshold_vector))
  352.       {
  353.         POSINC(previous_repetitions);
  354.         REALINC(distributed_cache_hits);
  355.         color->r += previous_diffuse.r * diffuse * new_surface.diffuse.r;
  356.         color->g += previous_diffuse.g * diffuse * new_surface.diffuse.g;
  357.         color->b += previous_diffuse.b * diffuse * new_surface.diffuse.b;
  358.         color->r += previous_specular.r * specular * new_surface.specular.r;
  359.         color->g += previous_specular.g * specular * new_surface.specular.g;
  360.         color->b += previous_specular.b * specular * new_surface.specular.b;
  361.       } else
  362.       {
  363.         ambient_diffuse_rays = estimate_diffuse(ambient_sample_rays, diffuse);
  364.         ambient_specular_rays = estimate_specular(ambient_sample_rays,
  365.           specular, new_surface.phong_factor);
  366.         if (shade_level < RAY_CACHE_LEVEL_MAX)
  367.           ray_node += RIGHT;
  368.         POSINC(shade_level);
  369.         if (shade_level > shade_level_max)
  370.           shade_level_max = shade_level;
  371.         if (SELF_INTERSECT(object->object_type, distributed.inside))
  372.           id = NO_OBJECTS;
  373.         else
  374.           id = object->id;
  375.         distributed.inside = ray->inside;
  376.         distributed.level.r = ray->level.r * surface_diffuse.r;
  377.         distributed.level.g = ray->level.g * surface_diffuse.g;
  378.         distributed.level.b = ray->level.b * surface_diffuse.b;
  379.         distributed_color.r = 0.0;
  380.         distributed_color.g = 0.0;
  381.         distributed_color.b = 0.0;
  382.         if (COLOR_BIG(surface_diffuse, ROUNDOFF)
  383.             AND COLOR_BIG(distributed.level, ROUNDOFF)
  384.             AND(ambient_diffuse_rays > 0))
  385.         {
  386.           /* Diffuse ambient */
  387.           for (l = 0; l < ambient_diffuse_rays; POSINC(l))
  388.           {
  389.             make_diffuse_vector(&old_normal, &(distributed.vector));
  390.             REALINC(ambient_rays);
  391.             if (intersect_all(id, position, &distributed, &new_color) > 0.0)
  392.             {
  393.               distributed_color.r += new_color.r;
  394.               distributed_color.g += new_color.g;
  395.               distributed_color.b += new_color.b;
  396.             } else
  397.             {
  398.               distributed_color.r += back_color.r;
  399.               distributed_color.g += back_color.g;
  400.               distributed_color.b += back_color.b;
  401.             }
  402.           }
  403.           k = 1.0 / (real) ambient_diffuse_rays;
  404.           distributed_color.r *= k;
  405.           distributed_color.g *= k;
  406.           distributed_color.b *= k;
  407.           color->r += distributed_color.r * diffuse * new_surface.diffuse.r;
  408.           color->g += distributed_color.g * diffuse * new_surface.diffuse.g;
  409.           color->b += distributed_color.b * diffuse * new_surface.diffuse.b;
  410.         }
  411.         if ((shade_level == 1) AND(distributed_cache_mode != 0))
  412.           STRUCT_ASSIGN(previous_diffuse, distributed_color);
  413.         distributed.level.r = ray->level.r * surface_specular.r;
  414.         distributed.level.g = ray->level.g * surface_specular.g;
  415.         distributed.level.b = ray->level.b * surface_specular.b;
  416.         distributed_color.r = 0.0;
  417.         distributed_color.g = 0.0;
  418.         distributed_color.b = 0.0;
  419.         if (COLOR_BIG(surface_specular, ROUNDOFF)
  420.             AND COLOR_BIG(distributed.level, ROUNDOFF)
  421.             AND(ambient_specular_rays > 0)
  422.             AND(new_surface.phong_factor > ROUNDOFF))
  423.         {
  424.           /* Specular ambient */
  425.           for (l = 0; l < ambient_specular_rays; POSINC(l))
  426.           {
  427.             make_specular_vector(&(reflected.vector), &old_normal,
  428.                                  new_surface.phong_factor,
  429.                                  &(distributed.vector));
  430.             REALINC(ambient_rays);
  431.             if (intersect_all(id, position, &distributed, &new_color) > 0.0)
  432.             {
  433.               distributed_color.r += new_color.r;
  434.               distributed_color.g += new_color.g;
  435.               distributed_color.b += new_color.b;
  436.             } else
  437.             {
  438.               distributed_color.r += back_color.r;
  439.               distributed_color.g += back_color.g;
  440.               distributed_color.b += back_color.b;
  441.             }
  442.           }
  443.           k = 1.0 / (real) ambient_specular_rays;
  444.           distributed_color.r *= k;
  445.           distributed_color.g *= k;
  446.           distributed_color.b *= k;
  447.           color->r += distributed_color.r * specular * new_surface.specular.r;
  448.           color->g += distributed_color.g * specular * new_surface.specular.g;
  449.           color->b += distributed_color.b * specular * new_surface.specular.b;
  450.         }
  451.         POSDEC(shade_level);
  452.         if (shade_level < RAY_CACHE_LEVEL_MAX)
  453.           ray_node -= RIGHT;
  454.         if ((shade_level == 0) AND(distributed_cache_mode != 0))
  455.         {
  456.           if (previous_repetitions > 0)
  457.           {
  458.             REALINC(distributed_cache_resets);
  459.             previous_repetitions = 0;
  460.           }
  461.           STRUCT_ASSIGN(previous_normal, old_normal);
  462.           STRUCT_ASSIGN(previous_reflected, reflected.vector);
  463.           STRUCT_ASSIGN(previous_specular, distributed_color);
  464.         }
  465.       }
  466.     }
  467.   }
  468.   /* Lights */
  469.   new_surface.diffuse.r *= new_surface.diffuse_factor.r;
  470.   new_surface.diffuse.g *= new_surface.diffuse_factor.g;
  471.   new_surface.diffuse.b *= new_surface.diffuse_factor.b;
  472.   for (l = 0; l < lights; POSINC(l))
  473.   {
  474.     vector_to_light(l, position, &lighting);
  475.     intensity = -1.0;
  476.     if ((texture_mode != 0) AND(object->texture != NULL)
  477.         AND normal_check_mode AND object->texture_modify_normal)
  478.     {
  479.       k = DOT_PRODUCT(old_normal, lighting);
  480.       diffuse = DOT_PRODUCT(*normal, lighting);
  481.       if ((k < 0.0) == (diffuse > 0.0))
  482.         diffuse = -diffuse;
  483.     } else
  484.       diffuse = DOT_PRODUCT(*normal, lighting);
  485.     if (diffuse < 0.0)
  486.     {
  487.       opposite_light = TRUE;
  488.       if (refractive AND(light_mode == 2))
  489.         diffuse = -diffuse;
  490.     } else
  491.       opposite_light = FALSE;
  492.     if ((diffuse > ROUNDOFF)
  493.         AND COLOR_BIG(surface_diffuse, ROUNDOFF))
  494.     {
  495.       intensity = light_intensity(l, &lighting);
  496.       diffuse *= intensity;
  497.     } else
  498.       diffuse = 0.0;
  499.     if (COLOR_BIG(surface_specular, ROUNDOFF))
  500.     {
  501.       if (opposite_light)
  502.         if (refractive AND(light_mode == 2))
  503.           specular = DOT_PRODUCT(refracted.vector, lighting);
  504.         else
  505.           specular = 0.0;
  506.       else
  507.         specular = DOT_PRODUCT(reflected.vector, lighting);
  508.       if (specular > ROUNDOFF)
  509.       {
  510.         if (intensity < 0.0)
  511.           intensity = light_intensity(l, &lighting);
  512.         if (intensity > ROUNDOFF)
  513.           specular = POWER(specular, new_surface.phong_factor) * intensity;
  514.         else
  515.           specular = 0.0;
  516.       }
  517.     } else
  518.       specular = 0.0;
  519.     if ((diffuse < ROUNDOFF) AND(specular < ROUNDOFF))
  520.     {
  521.       if (shade_level < LIGHT_CACHE_LEVEL_MAX)
  522.         light[l].cache_id[shade_level] = NO_OBJECTS;
  523.       continue;
  524.     }
  525.     k = calculate_factor(diffuse, geometric_incidence, &fresnel_specular);
  526.     new_specular.r = MIN(1.0, surface_specular.r + (surface_specular.r +
  527.       SPECULAR_PEAK) * k);
  528.     new_specular.g = MIN(1.0, surface_specular.g + (surface_specular.g +
  529.       SPECULAR_PEAK) * k);
  530.     new_specular.b = MIN(1.0, surface_specular.b + (surface_specular.b +
  531.       SPECULAR_PEAK) * k);
  532.     new_specular.r *= 1.0 + new_surface.metal_factor.r * (1.0 -
  533.       fresnel_specular) * (new_surface.color.r - 1.0);
  534.     new_specular.g *= 1.0 + new_surface.metal_factor.g * (1.0 -
  535.       fresnel_specular) * (new_surface.color.g - 1.0);
  536.     new_specular.b *= 1.0 + new_surface.metal_factor.b * (1.0 -
  537.       fresnel_specular) * (new_surface.color.b - 1.0);
  538.     light_brightness(object->id, l, position, &lighting, &brightness);
  539.     if (brightness.r > ROUNDOFF)
  540.     {
  541.       if (diffuse > ROUNDOFF)
  542.         color->r += diffuse * brightness.r * new_surface.diffuse.r;
  543.       if (specular > ROUNDOFF)
  544.         color->r += specular * brightness.r * new_specular.r;
  545.     }
  546.     if (brightness.g > ROUNDOFF)
  547.     {
  548.       if (diffuse > ROUNDOFF)
  549.         color->g += diffuse * brightness.g * new_surface.diffuse.g;
  550.       if (specular > ROUNDOFF)
  551.         color->g += specular * brightness.g * new_specular.g;
  552.     }
  553.     if (brightness.b > ROUNDOFF)
  554.     {
  555.       if (diffuse > ROUNDOFF)
  556.         color->b += diffuse * brightness.b * new_surface.diffuse.b;
  557.       if (specular > ROUNDOFF)
  558.         color->b += specular * brightness.b * new_specular.b;
  559.     }
  560.   }
  561. }
  562.